# -*-coding:utf-8-*-
"""
@project: python-project
@Time: 2023/12/1915:37
@Auth: Loneliness_Burial
@File: 扫雷.py
@Motto: 深情不改必坠死海
"""
import tkinter
import tkinter.messagebox
import random


# 通过路径获取图片
def get_image(filename, w=None, h=None):
    try:
        im = tkinter.PhotoImage(file=filename)
        if w != None and h != None:
            im = im.subsample(im.width() // w, im.height() // h)
        return im
    except:
        return None


class Sweep(tkinter.Button):
    map = []  # 地图
    w = 7  # 地图宽度
    h = 8  # 地图高度
    mine = 5  # 地雷个数
    x0 = 30  # 地图相对于主窗口的起点
    y0 = 50
    count = 0  # 扫除计数
    state = 0  # 0play 1vectroy 2over 游戏状态
    mine_size = 40  # 地图方块大小
    # 数字0~9的字体颜色rgb
    fgs = [(255, 255, 255), (9, 147, 62), (0, 187, 187), (240, 78, 0), (166, 19, 188)
        , (185, 122, 87), (136, 0, 21), (163, 73, 164), (0, 0, 0), (0, 0, 0)]
    # 方块状态颜色与背景图片
    bgs = [(128, 128, 128), (255, 255, 255), (0, 255, 0), (255, 0, 0), (255, 200, 0), (0, 255, 0), (163, 73, 164)]
    images = ['area.png', 'opened.png', 'flag.png', 'doubt.png', 'boom.png', 'sweeped.png', 'mistake.png']
    pic = []

    # 创建地图
    def create_map(w=w, h=h, mine=mine, x0=x0, y0=x0,
                   mine_size=mine_size, fgs=fgs, bgs=bgs, images=images):
        Sweep.w = w
        Sweep.h = h
        Sweep.mine = mine
        Sweep.x0 = x0
        Sweep.y0 = y0
        Sweep.mine_size = mine_size
        Sweep.fgs = fgs
        Sweep.bgs = bgs
        Sweep.images = images
        Sweep.state = 0
        Sweep.count = 0

        # 加载背景图片
        if not Sweep.pic:
            for filename in Sweep.images:
                image = get_image(filename, Sweep.mine_size, Sweep.mine_size)
                Sweep.pic.append(image)

    def init_map(root):

        size_str = '{}x{}+400+80'.format(Sweep.w * Sweep.mine_size + 80, Sweep.h * Sweep.mine_size + 100)
        root.geometry(size_str)

        Sweep.state = 0
        Sweep.count = 0

        for button in Sweep.map:
            button.destroy()
        Sweep.map.clear()
        root.update()

        random_numbers = random.sample(range(0, Sweep.w * Sweep.h), Sweep.mine)

        for i in range(Sweep.w * Sweep.h):
            r = i // Sweep.w
            c = i % Sweep.w
            n = 9 if i in random_numbers else 0
            button = Sweep(root)
            button.place(x=c * Sweep.mine_size + Sweep.x0, y=r * Sweep.mine_size + Sweep.y0
                         , width=Sweep.mine_size, height=Sweep.mine_size)
            button.setPos(r=r, c=c, n=n)

        for mine in Sweep.map:
            mine.map_mine()

        root.update()
        Sweep.reset_map()

    def reset_map():

        Sweep.state = 0
        for mine in Sweep.map:
            mine.state = 0
            mine.update_style()

    def __init__(self, master=None, cnf={}, **kw):

        super().__init__(master, cnf, **kw)

        self.text = self['text']
        self.command = self['command']
        self.bind('<Button-1>', self.clicked)
        self.bind('<Button-3>', self.right_clicked)
        self.r = 0
        self.c = 0
        self.n = 0
        self.state = 0  # 0没有被打开 1已经被打开 2被标志 3被质疑 4打开是雷被爆炸 5被扫除 6标志错误

        self.update_style()
        self.__class__.map.append(self)

    def clicked(self, event):

        if self.__class__.state != 0:
            # tkinter.messagebox.showinfo(title="游戏结束！",message = "游戏已经结束，请重新开始")
            return
        if self.state == 1: return

        if self.n == 9:
            self.gameover()
            return

        if self.n == 0:
            self.auto_sweep()
            self.vectory()
            return

        self.__class__.count += 1
        self.state = 1
        self.update_style()

        self.vectory()

    def right_clicked(self, event):

        if self.state == 1: return
        if self.state == 0:
            self.state = 2
        elif self.state == 2:
            self.state = 3
        elif self.state == 3:
            self.state = 0
        self.update_style()

    def setPos(self, r, c, n):
        self.r = r
        self.c = c
        self.n = n

    def map_mine(self):

        if self.n != 9:
            return

        neighbors = [(self.r + i, self.c + j) for i in range(-1, 2) for j in range(-1, 2) if i != 0 or j != 0]
        for r, c in neighbors:
            for mine in self.__class__.map:
                if mine.r == r and mine.c == c and mine.n != 9:
                    mine.n += 1

    def update_style(self):

        text = str("")
        if self.n != 0 and self.n != 9 and self.state == 1:  text = str(self.n)

        hex_fg = '#{:02x}{:02x}{:02x}'.format(self.__class__.fgs[self.n][0]
                                              , self.__class__.fgs[self.n][1],
                                              self.__class__.fgs[self.n][2])

        hex_bg = '#{:02x}{:02x}{:02x}'.format(self.__class__.bgs[self.state][0]
                                              , self.__class__.bgs[self.state][1],
                                              self.__class__.bgs[self.state][2])

        image = self.__class__.pic[self.state]
        self.image = image

        if self.state == 2:
            text = str("!")
            hex_fg = "red"
        elif self.state == 3:
            text = str("?")
            hex_fg = str("yellow")
        elif self.state == 6:
            text = str("×")
            hex_fg = str("red")

        if image != None:
            hex_bg = None

        self.configure(bg=hex_bg, fg=hex_fg, image=image, text=text, compound=tkinter.CENTER)

    def auto_sweep(self):

        if self.state == 1: return

        self.state = 1
        self.update_style()
        self.__class__.count += 1

        if self.n != 0:
            return

        neighbors = [(self.r + i, self.c + j) for i in range(-1, 2) for j in range(-1, 2) if i != 0 or j != 0]
        for r, c in neighbors:
            for mine in self.__class__.map:
                if mine.r == r and mine.c == c and mine.n != 9:
                    mine.clicked(None)

    def gameover(self):

        self.state = 4
        self.__class__.state = 2

        for mine in self.__class__.map:
            if mine.n == 9 and mine.state != 2:
                mine.state = 4
                mine.update_style()
            elif mine.n != 9 and mine.state == 2:
                mine.state = 6
                mine.update_style()

        tkinter.messagebox.showinfo(parent=self, title="游戏结束！", message="失败！")

    def vectory(self):
        if self.__class__.count == (self.__class__.h * self.__class__.w - self.__class__.mine):
            if self.__class__.state != 1:
                tkinter.messagebox.showinfo("游戏结束！", "恭喜过关！！！")
                self.__class__.state = 1


root = tkinter.Tk()


def del_menu(args):
    if args == "入门":
        Sweep.create_map(w=6, h=5, mine=1)
    elif args == "简单":
        Sweep.create_map(w=10, h=10, mine=15)
    elif args == "一般":
        Sweep.create_map(w=16, h=16, mine=40)
    elif args == "困难":
        Sweep.create_map(w=20, h=16, mine=60)
    elif args == "重新开始":
        pass
    Sweep.init_map(root)


if __name__ == '__main__':
    root.title('扫雷')
    Sweep.create_map(w=6, h=5, mine=3)
    Sweep.init_map(root)

    menu_bar = tkinter.Menu(root)
    root.config(menu=menu_bar)

    game_menu = tkinter.Menu(menu_bar, tearoff=False)
    menu_bar.add_cascade(label="游戏", menu=game_menu)

    game_menu.add_command(label="入门", command=lambda: del_menu("入门"))
    game_menu.add_command(label="简单", command=lambda: del_menu("简单"))
    game_menu.add_command(label="一般", command=lambda: del_menu("一般"))
    game_menu.add_command(label="困难", command=lambda: del_menu("困难"))
    game_menu.add_command(label="重新开始", command=lambda: del_menu("重新开始"))

    # root.iconbitmap('mine.ico')
    root.mainloop()
